Фази подій в JavaScript

Детальне пояснення фаз занурення, мети та спливання подій

Що таке фази подій?

Коли відбувається подія в DOM (наприклад, клік мишею), вона проходить через три фази:

Window (захоплення)
Document (захоплення)
HTML (захоплення)
Body (захоплення)
Div (захоплення)
Button (ціль)
Div (спливання)
Body (спливання)
HTML (спливання)
Document (спливання)
Window (спливання)

Детальний опис фаз

Фаза занурення (Capturing Phase)

Подія починається з найвищого елемента (window) і спускається вниз до цільового елемента.

Ця фаза також називається "фаза захоплення".

Використання: addEventListener(event, handler, true)

Фаза мети (Target Phase)

Подія досягає цільового елемента, на якому вона відбулася.

На цій фазі виконуються всі обробники, прикріплені до цільового елемента, незалежно від налаштувань capture.

Фаза спливання (Bubbling Phase)

Подія піднімається від цільового елемента назад до кореня документа.

Це фаза за замовчуванням для більшості обробників подій.

Використання: addEventListener(event, handler, false)

Параметр capture в addEventListener

Третій параметр методу addEventListener визначає, на якій фазі буде викликаний обробник:

// Обробник на фазі занурення (захоплення)
element.addEventListener('click', handler, true);
// або
element.addEventListener('click', handler, { capture: true });

// Обробник на фазі спливання (за замовчуванням)
element.addEventListener('click', handler, false);
// або
element.addEventListener('click', handler);
// або
element.addEventListener('click', handler, { capture: false });

Інтерактивна демонстрація

Натискайте на елементи нижче, щоб побачити, як подія проходить через різні фази. Спробуйте різні налаштування capture.

Дідівський елемент

Натисни мене!

Батьківський елемент

Натисни мене!

Дочірній елемент

Натисни мене!

Обробники на фазі занурення (capture: true):
Обробники на фазі спливання (capture: false):
Лог очищено
[07:49:24] Обробники подій додані. Натисніть на будь-який елемент!
[07:49:28] Батьківський елемент (захоплення)
[07:49:28] Батьківський елемент (спливання)
[07:49:31] Дочірній елемент (захоплення)
[07:49:31] Дочірній елемент (спливання)
[07:49:31] >>> Цільова фаза <<<

Практичні приклади використання

Приклад 1: Делегування подій

Використання спливання для делегування подій дозволяє обробляти події на батьківському елементі:

// HTML: <ul id="myList">
// <li>Елемент 1</li>
// <li>Елемент 2</li>
// </ul>

const list = document.getElementById('myList');

// Додаємо один обробник на батьківський елемент
list.addEventListener('click', function(event) {
  // Перевіряємо, чи клік був на елементі li
  if (event.target.tagName === 'LI') {
    console.log('Клік на елементі:', event.target.textContent);
  }
});

Приклад 2: Зупинка поширення події

Іноді потрібно зупинити подію, щоб вона не поширювалася далі:

const childElement = document.getElementById('child');

childElement.addEventListener('click', function(event) {
  console.log('Обробник дочірнього елемента');
  
  // Зупиняємо спливання події
  event.stopPropagation();
  
  // Або зупиняємо і спливання, і виконання інших обробників на цьому елементі
  // event.stopImmediatePropagation();
});

// Цей обробник не виконається через stopPropagation()
document.getElementById('parent').addEventListener('click', function() {
  console.log('Цей обробник не виконається');
});

Приклад 3: Використання фаз для спеціальних сценаріїв

Фаза занурення корисна, коли потрібно перехопити подію до того, як вона дійде до цільового елемента:

// Заборона кліків на всіх елементах, крім дозволених
document.addEventListener('click', function(event) {
  // Якщо елемент не має класу 'allowed-click'
  if (!event.target.classList.contains('allowed-click')) {
    event.stopPropagation();
    event.preventDefault();
    console.log('Клік заблоковано!');
  }
}, true); // Використовуємо фазу занурення

Короткий підсумок